/**
 * 
 */
package com.qunar.mina.app.service.impl;

import java.io.FileNotFoundException;
import java.util.Map;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MultiSearcher;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.WildcardQuery;
import org.apache.lucene.util.Version;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wltea.analyzer.lucene.IKQueryParser;

import com.qunar.mina.app.config.AnalyzerConfig;
import com.qunar.mina.app.config.DirectoryConfig;
import com.qunar.mina.app.model.SearcherModel;
import com.qunar.mina.app.service.SearchService;
import com.qunar.wireless.ugc.qcfclient.dto.QueryResult;

/**
 * @author tao.zhang
 */
public class Searcher implements SearchService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /*
     * 查询user 或 auditor 索引库
     */
    @Override
    public QueryResult searcherScan(String keyword, Integer firstResult, Integer maxResult, String searcherName,
            String... fields) {
        if (maxResult > 50) {
            throw new IllegalArgumentException("maxResult is too larger.");
        }

        if (fields.length == 0) {
            throw new IllegalArgumentException("query field must not null.");
        }
        IndexSearcher searcher = null;
        Query query = null;
        try {

            searcher = new IndexSearcher(DirectoryConfig.getFSDirectory(searcherName));
            query = new TermQuery(new Term(fields[0], keyword));

            long begin = System.currentTimeMillis();
            TopDocs topDocs = searcher.search(query, 1000);
            long end = System.currentTimeMillis();
            QueryResult qr = SearcherModel.getQueryResult(firstResult, maxResult, searcher, topDocs);
            logger.info("查询" + maxResult + "条记录共耗时：" + (end - begin) + "ms");

            return qr;
        } catch (FileNotFoundException e) {
            logger.info("索引库进行物理删除后，第一次检索会找不到索引" + e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            SearcherModel.closeSearcher(searcher);
        }
        return new QueryResult();

    }

    /*
     * 查询address 或 pic 索引库
     * @param
     */
    @Override
    public QueryResult searcher(String keyword, Integer firstResult, Integer maxResult, String searcherName,
            String... fields) {
        if (maxResult > 50) {
            throw new IllegalArgumentException("maxResult is too larger.");
        }

        if (fields.length == 0) {
            throw new IllegalArgumentException("query field must not null.");
        }

        IndexSearcher searcher = null;
        MultiSearcher multiSearcher = null;
        Query query = null;
        try {

            searcher = new IndexSearcher(DirectoryConfig.getFSDirectory(searcherName));

            multiSearcher = SearcherModel.getParallelMultiSearcher(searcher);
            
            query = IKQueryParser.parseMultiField(fields, keyword);
            
            System.out.println(query.toString());

            long begin = System.currentTimeMillis();
            TopDocs topDocs = multiSearcher.search(query, 1000);
            long end = System.currentTimeMillis();
            QueryResult qr = SearcherModel.getQueryResult(firstResult, maxResult, multiSearcher, topDocs);
            logger.info("查询" + maxResult + "条记录共耗时：" + (end - begin) + "ms");

            return qr;
        } catch (FileNotFoundException e) {
            logger.info("索引库进行物理删除后，第一次检索会找不到索引" + e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            SearcherModel.closeSearcher(searcher, multiSearcher);
        }
        return new QueryResult();
    }

    //test
    @Override
    public QueryResult boostSearcher(String keyword, Integer firstResult, Integer maxResult, String searcherName, Map<String,Float> boosts,
            String... fields) {
        if (maxResult > 50) {
            throw new IllegalArgumentException("maxResult is too larger.");
        }

        if (fields.length == 0) {
            throw new IllegalArgumentException("query field must not null.");
        }

        IndexSearcher searcher = null;
        MultiSearcher multiSearcher = null;
        MultiFieldQueryParser parser = null;
        Query query = null;
        Analyzer ik = AnalyzerConfig.getAnalyzer();
        try {

            searcher = new IndexSearcher(DirectoryConfig.getFSDirectory(searcherName));

            multiSearcher = SearcherModel.getParallelMultiSearcher(searcher);
            
            parser = new MultiFieldQueryParser(Version.LUCENE_30, fields, ik, boosts);
            
            //query = IKQueryParser.parseMultiField(fields, keyword);
            
            query = parser.parse(keyword);
            
            System.out.println(query.toString());

            long begin = System.currentTimeMillis();
            TopDocs topDocs = multiSearcher.search(query, 1000);
            long end = System.currentTimeMillis();
            QueryResult qr = SearcherModel.getQueryResult(firstResult, maxResult, multiSearcher, topDocs);
            logger.info("查询" + maxResult + "条记录共耗时：" + (end - begin) + "ms");

            return qr;
        } catch (FileNotFoundException e) {
            logger.info("索引库进行物理删除后，第一次检索会找不到索引" + e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            SearcherModel.closeSearcher(searcher, multiSearcher);
        }
        return new QueryResult();
    }
    
    /**
     * 景点或目的地搜索
     */
    @Override
    public QueryResult POISearcher(String keyword, Boolean isDestin, Integer firstResult, Integer maxResult,
            String searcherName, String... fields) {
        if (maxResult > 50) {
            throw new IllegalArgumentException("maxResult is too larger.");
        }

        if (fields.length == 0) {
            throw new IllegalArgumentException("query field must not null.");
        }

        IndexSearcher searcher = null;
        MultiSearcher multiSearcher = null;
        Query nameQuery = null;
        Query destinationQuery = null;
        Query isValid = null;
        Query openType = null;
        PrefixQuery pq = null;
        BooleanQuery bq = new BooleanQuery();
        try {

            searcher = new IndexSearcher(DirectoryConfig.getFSDirectory(searcherName));

            multiSearcher = SearcherModel.getParallelMultiSearcher(searcher);

            nameQuery = IKQueryParser.parse("name", keyword);
            bq.add(nameQuery, BooleanClause.Occur.MUST);

            /** 是否是目的地 */
            if (isDestin) {
                destinationQuery = new TermQuery(new Term("isDestination", "1"));
                bq.add(destinationQuery, BooleanClause.Occur.MUST);
            }
            /** 是否合法 */
            isValid = new TermQuery(new Term("isValid", "1"));
            bq.add(isValid, BooleanClause.Occur.MUST);

            /** 是否开放 */
            openType = new TermQuery(new Term("openType", "1"));
            bq.add(openType, BooleanClause.Occur.MUST);
            
            
//            pq = new PrefixQuery(new Term("pinyin","bj"));
//            bq.add(pq, BooleanClause.Occur.SHOULD);

            long begin = System.currentTimeMillis();
            TopDocs topDocs = searcher.search(bq, 1000);
            long end = System.currentTimeMillis();
            QueryResult qr = SearcherModel.getQueryResult(firstResult, maxResult, multiSearcher, topDocs);
            logger.info("查询" + maxResult + "条记录共耗时：" + (end - begin) + "ms");

            return qr;
        } catch (FileNotFoundException e) {
            logger.info("索引库进行物理删除后，第一次检索会找不到索引" + e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            SearcherModel.closeSearcher(searcher, multiSearcher);
        }
        return new QueryResult();
    }

    /**
     * 通配符查询
     */
    @Override
    public QueryResult wildcardSearcher(String keyword, Integer firstResult, Integer maxResult, String field) {
        if (maxResult > 50) {
            throw new IllegalArgumentException("maxResult is too larger.");
        }

        if (field == null || "".equals(field)) {
            throw new IllegalArgumentException("query field must not null.");
        }

        IndexSearcher searcher = null;
        Query query = null;
        try {
            searcher = new IndexSearcher(DirectoryConfig.getFSUserDirectory());
            query = new WildcardQuery(new Term(field, keyword));

            long begin = System.currentTimeMillis();
            TopDocs topDocs = searcher.search(query, 1000);
            long end = System.currentTimeMillis();
            QueryResult qr = SearcherModel.getQueryResult(firstResult, maxResult, searcher, topDocs);

            logger.info("通配符查询" + maxResult + "条记录共耗时：" + (end - begin) + "ms");

            return qr;
        } catch (FileNotFoundException e) {
            logger.info("索引库进行物理删除后，第一次检索会找不到索引" + e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            SearcherModel.closeSearcher(searcher);
        }
        return new QueryResult();
    }

    /**
     * 模糊匹配查询
     */
    @Override
    public QueryResult fuzzySearcher(String keyword, Integer firstResult, Integer maxResult, String field) {

        if (maxResult > 50) {
            throw new IllegalArgumentException("maxResult is too larger.");
        }

        if (field == null || "".equals(field)) {
            throw new IllegalArgumentException("query field must not null.");
        }

        IndexSearcher searcher = null;
        Query query = null;
        try {
            searcher = new IndexSearcher(DirectoryConfig.getFSUserDirectory());
            query = new FuzzyQuery(new Term(field, keyword));

            long begin = System.currentTimeMillis();
            TopDocs topDocs = searcher.search(query, 1000);
            long end = System.currentTimeMillis();
            QueryResult qr = SearcherModel.getQueryResult(firstResult, maxResult, searcher, topDocs);

            logger.info("模糊查询" + maxResult + "条记录共耗时：" + (end - begin) + "ms");

            return qr;
        } catch (FileNotFoundException e) {
            logger.info("索引库进行物理删除后，第一次检索会找不到索引" + e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            SearcherModel.closeSearcher(searcher);
        }
        return new QueryResult();

    }

}
